Skip to content

feat(audit): codebase-state auditor framework + file-size probe (#156)#161

Merged
hadamrd merged 1 commit into
trunkfrom
loop/156-feat-audit-codebase-state-auditor-catche
May 30, 2026
Merged

feat(audit): codebase-state auditor framework + file-size probe (#156)#161
hadamrd merged 1 commit into
trunkfrom
loop/156-feat-audit-codebase-state-auditor-catche

Conversation

@hadamrd
Copy link
Copy Markdown
Owner

@hadamrd hadamrd commented May 30, 2026

Closes #156.

Summary

  • New forge_loop.codebase_audit module: Probe Protocol, Violation, AuditReport, audit() orchestrator with per-probe crash isolation, plus file_violations() that files one ticket per violation with idempotent dedup against the audit:probe-<name> label + body footer.
  • New forge_loop.audit_probes.file_size — first probe. Per-language soft caps (Py 500, TS/JS 400, Java 600); P1 escalation at ≥2× soft cap. Today it correctly flags cli.py (1700 LOC) as P1.
  • New typed events AuditViolationFiledEvent and AuditCleanEvent registered in events.py.
  • New forge-loop audit CLI subcommand: dry-run by default, --apply files tickets, --json for scripts. Dry-run NEVER constructs a gh client.
  • runner/tick._run_codebase_audit wired to the maintenance_every_n_ticks cadence — emits audit_violation_observed / audit_clean events so the dashboard surfaces drift. Operator runs --apply explicitly.

Acceptance (from #156)

  • forge_loop/codebase_audit.py with audit(repo, manifesto) -> AuditReport
  • forge-loop audit CLI command (dry-run by default; --apply files tickets)
  • Runs on maintenance_every_n_ticks cadence by default
  • Each violation → one ticket, axis-labeled modernization-gated, rationale citing manifesto + acceptance scaffolded
  • Typed events audit_violation_filed, audit_clean
  • Tests: fixture codebase with planted violations → assert correct tickets filed

Manifesto compliance

The "state-based rules need a state-based gate" manifesto rule (added by #157) calls for exactly this. The framework is the unlock — follow-up sub-tickets (Any-typed-file, deprecated-pattern, cyclomatic, coverage) each ship a probe under audit_probes/ without re-touching the framework.

Test plan

  • tests/test_codebase_audit.py — 23 tests, all green.
  • T1 (state-machine edges): BoomProbe exercises the probe-crash default-branch.
  • T2 (adversarial / sad path): missing file, binary file, missing config, gh create failure, idempotent dedup.
  • CLI integration test drives _cmd_audit end-to-end against MockGhClient and asserts the right label set + event emission.
  • test_events.py, test_cli.py, test_stuck_sweep.py still green (no regressions).
  • Smoke: python -m forge_loop audit --json against this worktree correctly surfaces cli.py and other oversized files.

🤖 Generated with Claude Code

The per-PR critic reviews diffs and never sees cumulative state. cli.py
grew to 1700+ LOC, 3.4x the manifesto soft-cap for Python, one
reasonable-looking 50-100 LOC commit at a time. Same boiling-frog shape
as stale issues (#129) and stale branches (#146).

This change adds the framework that closes that gap:

* forge_loop.codebase_audit: Probe Protocol, AuditReport, audit()
  orchestrator with per-probe error isolation, walk_source_files()
  honoring vendor/build ignore dirs, and file_violations() that files
  one ticket per violation with idempotent dedup against the
  audit:probe-<name> label footer.
* forge_loop.audit_probes.file_size: first probe. Per-language soft
  caps (Python 500, TS/JS 400, Java 600). Hard-multiplier escalates
  severity to P1 when a file is >= 2x its soft cap (today: cli.py).
* Typed events AuditViolationFiledEvent / AuditCleanEvent registered
  in forge_loop.events.
* forge-loop audit CLI command: dry-run by default, --apply files
  tickets, --json for scripts/dashboards. Dry-run path never
  constructs a gh client.
* runner/tick._run_codebase_audit: runs on the maintenance_every_n_ticks
  cadence and emits audit_violation_observed / audit_clean. Side-effect-
  free on the runner side; operator drives --apply explicitly.
* tests/test_codebase_audit.py: 23 tests covering happy path, probe
  crash isolation (T1 default-branch + T2 sad-path), threshold edges,
  language-specific caps, idempotent dedup against the footer,
  create_issue failure surfacing (T3), clean-event-only path, and the
  CLI dry-run / json / --apply variants.

Manifesto compliance: every new event KIND uses the typed registry; no
new os.environ.get; no new subprocess shell-out; cross-module event KIND
strings live in events.py with the rest. Adversarial probes (BoomProbe)
exercise the default-branch isolation per T1.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@hadamrd hadamrd merged commit f0bb2a0 into trunk May 30, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(audit): codebase-state auditor — catches manifesto violations the per-PR critic can't see (boiling-frog gap)

1 participant